package cn.cloudtogo.server.mongo;

import cn.cloudtogo.common.GendbException;
import cn.cloudtogo.common.model.ExternalDatasourceDao;
import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.types.ConnectString;
import cn.cloudtogo.common.types.RequestHeaderObject;
import cn.cloudtogo.common.util.MongoConnectionHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static cn.cloudtogo.common.types.RequestHeaderObject.extractExternalDatasourceModel;

/**
 * @author yaolianhua789@gmail.com
 **/
@Component
@Slf4j
public class SpringMongoTemplateContext {

    public final Map<String, MongoTemplate> mongoTemplateContainer = new ConcurrentHashMap<>(32);
    private final ExternalDatasourceDao externalDatasourceDao;

    public SpringMongoTemplateContext(ExternalDatasourceDao externalDatasourceDao) {
        this.externalDatasourceDao = externalDatasourceDao;
    }

    public synchronized void putMongoTemplate(RequestHeaderObject object, MongoTemplate mongoTemplate) {
        mongoTemplateContainer.put(object.getUuid(), mongoTemplate);
    }

    public synchronized void remove(RequestHeaderObject requestHeaderObject) {
        mongoTemplateContainer.remove(requestHeaderObject.getUuid());
    }

    public synchronized MongoTemplate getMongoTemplate(RequestHeaderObject o) {
        ExternalDatasourceModel model = extractExternalDatasourceModel(o);
        if (!isValid(model)) {
            throw new GendbException("key has been removed");
        }
        MongoTemplate mongoTemplate = mongoTemplateContainer.get(o.getUuid());
        //
        if (mongoTemplate == null) {
            ConnectString connectString = ConnectString.getConnectString(model.getUrl());
            boolean validConnection = MongoConnectionHelper.isValidConnection(connectString);
            if (validConnection) {
                log.info("get mongoTemplate null from memory, create new one and return [{}]", model);
                MongoTemplate templateNew = MongoConnectionHelper.getMongoTemplate(connectString);
                this.putMongoTemplate(o, templateNew);
                return templateNew;
            }
            throw new GendbException(String.format("key is invalid [%s]", o.getUuid()));
        }

        return mongoTemplate;
    }

    private boolean isValid(ExternalDatasourceModel model) {
        ExternalDatasourceModel one = externalDatasourceDao.query(model.getUuid());
        return one != null;
    }

}
